package com.boarsoft.boar.code.analysis.service.impl;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import com.boarsoft.boar.code.analysis.service.BeanAnalysis;
import com.boarsoft.boar.code.bean.biz.BeanInfoBiz;
import com.boarsoft.boar.code.bean.biz.BeanPropBiz;
import com.boarsoft.boar.code.bean.biz.BeanPropTreeBiz;
import com.boarsoft.boar.code.entity.BeanInfo;
import com.boarsoft.boar.code.entity.BeanProp;
import com.boarsoft.common.Util;
import com.github.javaparser.StaticJavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.ImportDeclaration;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.PackageDeclaration;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.FieldDeclaration;
import com.github.javaparser.ast.body.VariableDeclarator;

@Component("beanAnalysis")
public class BeanAnalysisImpl implements BeanAnalysis {
	private static final Logger log = LoggerFactory.getLogger(BeanAnalysisImpl.class);

	private static final String SKIP_FIELD = "serialVersionUID";
	@Autowired
	private BeanInfoBiz beanInfoBiz;

	@Autowired
	private BeanPropBiz beanPropBiz;
	@Autowired
	private BeanPropTreeBiz beanPropTreeBiz;

	@Override
	public void execute(String info) {
		try {
			CompilationUnit cu = StaticJavaParser.parse(info);
			List<FieldDeclaration> fds = cu.findAll(FieldDeclaration.class);
			List<ImportDeclaration> ids = cu.findAll(ImportDeclaration.class);
			List<ClassOrInterfaceDeclaration> cds = cu.findAll(ClassOrInterfaceDeclaration.class);
			List<PackageDeclaration> pds = cu.findAll(PackageDeclaration.class);
			String beanId = this.saveBean(cds, pds);
			if (!Util.strIsEmpty(beanId)) {
				this.saveBeanProp(beanId,this.getBeanType(pds, cds), fds, pds, ids);
			}
			this.deleteBeanPropTreeInfo(beanId);

		} catch (Exception e) {
			log.error("bean转换错误");
		}
	}

	/**
	 * 删除中间表信息
	 * 
	 * @param beanId
	 *            beanId
	 */
	private void deleteBeanPropTreeInfo(String beanId) {
		beanPropTreeBiz.delete(beanId);
	}

	/**
	 *
	 */
	private String saveBean(List<ClassOrInterfaceDeclaration> cds,List<PackageDeclaration> pds) {
		BeanInfo beanInfo = new BeanInfo();
		String beanType = this.getBeanType(pds, cds);
		beanInfo.setName(this.getBeanName(cds));
		beanInfo.setType(beanType);
		String beanId = null;
		try {
			beanId = beanInfoBiz.save(beanInfo);
		} catch (DataIntegrityViolationException e) {
			beanId = beanInfoBiz.findBeanInfoByType(beanType).get(0).getId();
		}
		return beanId;
	}

	/**
	 * 保存bean属性信息
	 * 
	 * @param beanId
	 *            beanId
	 */
	private void saveBeanProp(String beanId,String beanType, List<FieldDeclaration> fds, List<PackageDeclaration> pds, List<ImportDeclaration> ids) {
		List<BeanProp> beanProps = new ArrayList<>();
		for (FieldDeclaration fieldDeclaration : fds) {
			NodeList<VariableDeclarator> vdList = fieldDeclaration.getVariables();
			for (VariableDeclarator variableDeclarator : vdList) {
				// 获取字段名称
				String fieldName = variableDeclarator.getName().toString();
				// 获取字段类型
				String fieldtype = variableDeclarator.getType().toString();
				//如果是Map
				beanProps.addAll(handleCompInfo(beanId,beanType,fieldName,fieldtype,beanProps,pds,ids));
			}

		}
		if(!CollectionUtils.isEmpty(beanProps)){
			beanProps.forEach(beanProp -> {
				try {
					beanPropBiz.save(beanProp);
				} catch (DataIntegrityViolationException e) {

				}
			});
		}
		this.deleteInvalidInfo(beanProps, beanId);
	}


	public List<BeanProp> handleCompInfo(String beanId,String beanType,String fieldName,String fieldtype,List<BeanProp> beanProps, List<PackageDeclaration> pds, List<ImportDeclaration> ids){
		BeanProp beanProp = new BeanProp();
		beanProp.setBeanId(beanId);
		beanProp.setName(fieldName);
		beanProp.setType(typeConvert(fieldtype,pds,ids));
		beanProp.setModifier("");
		if(fieldtype.startsWith("Map<")){
			String values = fieldtype.substring(fieldtype.indexOf("<")+1,fieldtype.length()-1);
			String key = values.substring(0,values.indexOf(",")).trim();
			String value = values.substring(values.indexOf(",")+1).trim();
			beanProp.setKey(typeConvert(key,pds,ids));
			beanProp.setValue(typeConvert(value,pds,ids));
			beanProp.setBeanClazz(beanType);
			if (!SKIP_FIELD.equals(fieldName)) {
				beanProps.add(beanProp);
			}
			//如果
			if(value.contains("<")){
				 this.handleCompInfo(beanId,beanType,fieldName.concat(".value"),value ,beanProps,pds,ids);
			}
			/*try {
				beanPropBiz.save(beanProp);
			} catch (DataIntegrityViolationException e) {

			}*/
		} else if(fieldtype.startsWith("List<")){
			String value = fieldtype.substring(fieldtype.indexOf("<")+1,fieldtype.indexOf(">")).trim();
			beanProp.setKey("int");
			beanProp.setValue(typeConvert(value,pds,ids));
			beanProp.setBeanClazz(beanType);
			if (!SKIP_FIELD.equals(fieldName)) {
				beanProps.add(beanProp);
			}
			if(value.contains("<")){
				this.handleCompInfo(beanId,beanType,"list",value ,beanProps,pds,ids);
			}
		} else {
			if (!SKIP_FIELD.equals(fieldName)) {
				beanProps.add(beanProp);
			}
		}

		return beanProps;

	}
	/*private void handleCompInfo(String beanId,String name,String type){
		//如果是Map
		if(type.contains("(")){
			//获取括号前
			String typeStr = type.substring(0, type.indexOf("("));

		}
	}*/

	/**
	 * 删除无用数据
	 * 
	 * @param beanProps
	 *            bean属性列表
	 * @param beanId
	 *            beanID
	 */
	private void deleteInvalidInfo(List<BeanProp> beanProps, String beanId) {
		List<BeanProp> beanPropList = beanPropBiz.findBeanPropByBeanId(beanId, null);
		if (CollectionUtils.isEmpty(beanPropList)) {
			return;
		}
		for (BeanProp beanProp : beanPropList) {
			boolean flag = true;
			for (BeanProp beanProp1 : beanProps) {
				if (beanProp.getName().equals(beanProp1.getName()) && beanProp.getType().equals(beanProp1.getType())) {
					flag = false;
					break;
				}
			}
			if (flag) {
				beanPropBiz.delete(beanProp.getId());
			}
		}
	}

	/**
	 * 转换类型
	 *
	 * @param type
	 *            类型
	 * @return 实际类型
	 */
	public String typeConvert(String type,List<PackageDeclaration> pds,List<ImportDeclaration> ids) {
		switch (type) {
			case "String": {
				return "java.lang.String";
			}
			case "int": {
				return "int";
			}
			case "long": {
				return "long";
			}
			case "short": {
				return "short";
			}
			case "boolean": {
				return "boolean";
			}
			case "double": {
				return "double";
			}
			case "float": {
				return "float";
			}
			case "byte": {
				return "byte";
			}
			case "char": {
				return "char";
			}
			case "void": {
				return "void";
			}
			case "Void": {
				return "java.lang.Void";
			}
			case "Long": {
				return "java.lang.Long";
			}
			case "Boolean": {
				return "java.lang.Boolean";
			}
			case "Byte": {
				return "java.lang.Byte";
			}
			case "Character": {
				return "java.lang.Character";
			}
			case "Double": {
				return "java.lang.Double";
			}
			case "Float": {
				return "java.lang.Float";
			}
			case "Integer": {
				return "java.lang.Integer";
			}
			case "Short": {
				return "java.lang.Short";
			}
			case "Object": {
				return "java.lang.Object";
			}
			default: {
				/*if (type.contains("[")) {
					return typeConvert(type.substring(0, type.indexOf("[")),pds,ids).concat(type.substring(type.indexOf("[")));
				} else if (type.contains("(")) {
					return typeConvert(type.substring(0, type.indexOf("(")),pds,ids).concat(type.substring(type.indexOf("(")));
				} else if (type.contains("<")) {
					return typeConvert(type.substring(0, type.indexOf("<")),pds,ids).concat(type.substring(type.indexOf("<")));
				} else if (type.contains("{")) {
					return typeConvert(type.substring(0, type.indexOf("{")),pds,ids).concat(type.substring(type.indexOf("{")));
				}*/
				if(type.startsWith("Map<")){
					return "java.util.Map";
				}
				if(type.startsWith("List<")){
					return "java.util.List";
				}
				for (ImportDeclaration importDeclaration : ids) {
					String importName = importDeclaration.getName().toString();
					if (importName.endsWith(type)) {
						return importName;
					}
				}
				return pds.get(0).getName().toString().concat(".").concat(type);
				/*return getString(type, pds, ids);*/
			}
		}
	}

	/*static String getString(String type, List<PackageDeclaration> pds, List<ImportDeclaration> ids) {

	}*/

	public String getBeanType(List<PackageDeclaration> pds,List<ClassOrInterfaceDeclaration> cds) {
		return pds.get(0).getName().toString().concat(".").concat(cds.get(0).getName().toString());
	}

	public String getBeanName(List<ClassOrInterfaceDeclaration> cds) {
		return cds.get(0).getName().toString();
	}
}
